import jsSHA from 'jssha';
import { base32Decode } from './base32';
import { intToByte, fixedOne } from './intByte';

interface IOPENSSL {
  [key: string]: string;
}
/**
 * jsSHA中的OpenSSL算法
 * @type {Object.<string, string>}
 */
export const OPENSSL_TO_SHA_ALGO: IOPENSSL = {
  SHA1: 'SHA-1',
  SHA224: 'SHA-224',
  SHA256: 'SHA-256',
  SHA384: 'SHA-384',
  SHA512: 'SHA-512',
  'SHA3-224': 'SHA3-224',
  'SHA3-256': 'SHA3-256',
  'SHA3-384': 'SHA3-384',
  'SHA3-512': 'SHA3-512',
} as const;

/**ZZ
 * 计算HMAC
 * @param {ArrayBuffer} message 消息
 * @param {ArrayBuffer} key Key
 * @param {string} algorithm 算法
 * @returns {ArrayBuffer} ArrayBuffer
 */
export const hmacDigest = (message: any, key: any, digits = 6, algorithm = 'SHA1'): string => {
  // 设定加密方式
  const variant: any = OPENSSL_TO_SHA_ALGO[algorithm.toUpperCase()];
  let hmacObj = new jsSHA(variant, 'BYTES');
  // 设定密钥
  let token: any = base32Decode(key.toUpperCase());
  hmacObj.setHMACKey(token, 'BYTES');
  // 设定加密信息
  hmacObj.update(intToByte(message));
  let hmac = hmacObj.getHMAC('BYTES');
  // bytes对象转换成数组
  let hmac_a = hmac.split('');
  let offset = hmac_a[hmac_a.length - 1].charCodeAt(0) & 0xf;
  // 计算数字
  let code =
    ((hmac_a[offset].charCodeAt(0) & 0x7f) << 24) |
    ((hmac_a[offset + 1].charCodeAt(0) & 0xff) << 16) |
    ((hmac_a[offset + 2].charCodeAt(0) & 0xff) << 8) |
    (hmac_a[offset + 3].charCodeAt(0) & 0xff);
  let str_code: string = (code % Math.pow(10, digits)).toString();
  // 长度不足补1
  str_code = fixedOne(Number(str_code), digits);
  return str_code;
};
